﻿using Mbl.ParameterizedTest.FluentCollectionBuilding;
using System;

namespace Mbl.ParameterizedTest
{
    public class TestCase<TIn1, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1> InputRow { get; }

        public TestCase(TestInput<TIn1> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

    public class TestCase<TIn1, TIn2, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1, TIn2> InputRow { get; }

        public TestCase(TestInput<TIn1, TIn2> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;
        public TIn2 In2 => InputRow.In2;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

    public class TestCase<TIn1, TIn2, TIn3, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1, TIn2, TIn3> InputRow { get; }

        public TestCase(TestInput<TIn1, TIn2, TIn3> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;
        public TIn2 In2 => InputRow.In2;
        public TIn3 In3 => InputRow.In3;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

    public class TestCase<TIn1, TIn2, TIn3, TIn4, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1, TIn2, TIn3, TIn4> InputRow { get; }

        public TestCase(TestInput<TIn1, TIn2, TIn3, TIn4> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;
        public TIn2 In2 => InputRow.In2;
        public TIn3 In3 => InputRow.In3;
        public TIn4 In4 => InputRow.In4;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

    public class TestCase<TIn1, TIn2, TIn3, TIn4, TIn5, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1, TIn2, TIn3, TIn4, TIn5> InputRow { get; }

        public TestCase(TestInput<TIn1, TIn2, TIn3, TIn4, TIn5> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;
        public TIn2 In2 => InputRow.In2;
        public TIn3 In3 => InputRow.In3;
        public TIn4 In4 => InputRow.In4;
        public TIn5 In5 => InputRow.In5;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

    public class TestCase<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TOut> : JustifiedTestCase
    {
        public TestInput<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6> InputRow { get; }

        public TestCase(TestInput<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6> inputRow)
        {
            InputRow = inputRow;            
        }

        public TIn1 In1 => InputRow.In1;
        public TIn2 In2 => InputRow.In2;
        public TIn3 In3 => InputRow.In3;
        public TIn4 In4 => InputRow.In4;
        public TIn5 In5 => InputRow.In5;
        public TIn6 In6 => InputRow.In6;

        public IExpectation<TOut> Expectation { get; set; }

        public override string Justification { get; set; }

        public TestCaseAssertionResult HoldsFor(Func<TOut> actual)
        {
            var assertionResult = Expectation.HoldsFor(actual);
            if (assertionResult.Holds)
            {
                return TestCaseAssertionResult.Success;
            }

            return TestCaseAssertionResult.Error(this, assertionResult.ErrorMessage);
        }
    }

}